/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xuidemo.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.ToastDialog;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

import com.xuexiang.xui_lib.component.toast.XToast;
import com.xuexiang.xuidemo.ResourceTable;
import com.xuexiang.xuidemo.util.AppCfig;
import com.xuexiang.xuidemo.util.ElementHelper;
import com.xuexiang.xuidemo.util.Shareprefance;
import com.xuexiang.xuidemo.util.ToastUtil;
import com.xuexiang.xuidemo.view.CustomEditText;

/**
 * 登录页
 *
 * @since 2021-03-27
 */
public class LoginAbilitySlice extends AbilitySlice implements Component.ClickedListener {
    /**
     * 存储是否确认过隐私协议的变量key
     */
    public static final String USER_PRIVACY_AGREE = "privacy_agreement";
    private static final int DIALOG_WIDTH = 300;
    private static final int MSG_COUNT_DOWN = 0x1;
    private static final int MAX_COUNT_DOWN = 60;
    private static final int TOAST_OFFSET = 25;
    private int maxCountDown = MAX_COUNT_DOWN;
    private final int maxVerifyCodeLimit = 4;
    private CustomEditText etPhoneNumber;
    private CustomEditText etVerifyCode;
    private Button btnGetVerifyCode;
    private Image btnClearPhone;
    private Text verifyCodeCounter, phoneNumberErrorHint, verifyCodeErrorHint;
    private Shareprefance shareprefance;

    private CustomEditText.OnTextCursorChangedListener phoneChangedListener =
        new CustomEditText.OnTextCursorChangedListener() {
            @Override
            public void onCursorChange(TextField textField, int posStart, int posAfter) {
                if (posStart >= 1) {
                    btnClearPhone.setVisibility(Component.VISIBLE);
                } else {
                    btnClearPhone.setVisibility(Component.INVISIBLE);
                }
                phoneNumberNotError();
            }
        };

    private CustomEditText.OnFocusChangedListener edPhoneNumberFocusChangedListener =
        new CustomEditText.OnFocusChangedListener() {
            @Override
            public void onFocusChange(Component component, boolean isFocused) {
                if (isFocused && etPhoneNumber.getText().length() > 0) {
                    btnClearPhone.setVisibility(Component.VISIBLE);
                } else {
                    btnClearPhone.setVisibility(Component.INVISIBLE);
                }
            }
        };

    private CustomEditText.OnTextCursorChangedListener verifyCodeChangedListener =
        new CustomEditText.OnTextCursorChangedListener() {
            @Override
            public void onCursorChange(TextField textField, int posStart, int posAfter) {
                verifyCodeCounter.setText(posAfter + " / " + maxVerifyCodeLimit);
                if (posAfter > maxVerifyCodeLimit) {
                    etVerifyCode.setInputError(true);
                    verifyCodeCounter.setTextColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
                } else {
                    etVerifyCode.setInputError(false);
                    verifyCodeCounter.setTextColor(ElementHelper.getColor(getContext(),
                        ResourceTable.Color_gray_light));
                }
                verifyCodeErrorHint.setVisibility(Component.INVISIBLE);
            }
        };

    private CustomEditText.OnFocusChangedListener edVerifyCodeFocusChangedListener =
        new CustomEditText.OnFocusChangedListener() {
            @Override
            public void onFocusChange(Component component, boolean isFocused) {
                if (isFocused || etVerifyCode.isInputError()) {
                    verifyCodeCounter.setVisibility(Component.VISIBLE);
                } else {
                    verifyCodeCounter.setVisibility(Component.INVISIBLE);
                }
            }
        };

    private final EventHandler countDownTimer = new EventHandler(EventRunner.current()) {
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (maxCountDown <= 0) {
                btnGetVerifyCode.setEnabled(true);
                btnGetVerifyCode.setText(getString(ResourceTable.String_reget_verify_code));
                btnGetVerifyCode.setTextColor(ElementHelper.getColor(getContext(), ResourceTable.Color_login_blue_light));
                btnGetVerifyCode.setBackground(new ShapeElement(getContext(), ResourceTable.Graphic_btn_code_background));
                return;
            }
            maxCountDown--;
            btnGetVerifyCode.setText("    " + maxCountDown + "s    ");
            btnGetVerifyCode.setTextColor(ElementHelper.getColor(getContext(), ResourceTable.Color_login_gray_light));
            btnGetVerifyCode.setBackground(new ShapeElement(getContext(),
                ResourceTable.Graphic_btn_code_background_unable));
            final int delay = 1000;
            countDownTimer.sendEvent(MSG_COUNT_DOWN, delay);
        }
    };

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        setUIContent(ResourceTable.Layout_ability_login);
        etPhoneNumber = (CustomEditText) findComponentById(ResourceTable.Id_et_phone_number);
        etPhoneNumber.addTextCursorChangedListener(phoneChangedListener);
        etPhoneNumber.addOnFocusChangedListener(edPhoneNumberFocusChangedListener);
        verifyCodeCounter = (Text) findComponentById(ResourceTable.Id_verify_code_counter);
        verifyCodeCounter.setText(0 + " / " + maxVerifyCodeLimit);
        verifyCodeErrorHint = (Text) findComponentById(ResourceTable.Id_verify_code_error_hint);
        phoneNumberErrorHint = (Text) findComponentById(ResourceTable.Id_phone_number_error_hint);
        etVerifyCode = (CustomEditText) findComponentById(ResourceTable.Id_et_verify_code);
        etVerifyCode.addTextCursorChangedListener(verifyCodeChangedListener);
        etVerifyCode.addOnFocusChangedListener(edVerifyCodeFocusChangedListener);
        btnGetVerifyCode = (Button) findComponentById(ResourceTable.Id_btn_get_verify_code);
        btnGetVerifyCode.setClickedListener(this);
        btnClearPhone = (Image) findComponentById(ResourceTable.Id_clear_phone);
        btnClearPhone.setClickedListener(this);
        Image btnBack = (Image) findComponentById(ResourceTable.Id_btn_back);
        btnBack.setClickedListener(this);
        Text loginMode = (Text) findComponentById(ResourceTable.Id_tv_other_login);
        loginMode.setClickedListener(this);
        Text forgetPwd = (Text) findComponentById(ResourceTable.Id_tv_forget_password);
        forgetPwd.setClickedListener(this);
        Button confirm = (Button) findComponentById(ResourceTable.Id_btn_login);
        confirm.setClickedListener(this);
        Text userDeal = (Text) findComponentById(ResourceTable.Id_tv_user_protocol);
        userDeal.setClickedListener(this);
        Text userPrivacy = (Text) findComponentById(ResourceTable.Id_tv_privacy_protocol);
        userPrivacy.setClickedListener(this);
        shareprefance = new Shareprefance(getContext());
        shareprefance.initDB();
        boolean isAcceptPrivacy = shareprefance.select(USER_PRIVACY_AGREE);
        if (!isAcceptPrivacy) {
            showPrivacyDialog();
        }
    }

    private void showPrivacyDialog() {
        final CommonDialog dialog = new CommonDialog(getContext());
        final int dialogHeightVp = 410;
        int dialogHeight = AttrHelper.vp2px(dialogHeightVp, this);
        int dialogWidth = AttrHelper.vp2px(DIALOG_WIDTH, this);
        dialog.setSize(dialogWidth, dialogHeight);
        Component rootView = LayoutScatter.getInstance(getContext()).parse(
            ResourceTable.Layout_user_privacy_dialog, null, true);
        dialog.setContentCustomComponent(rootView);
        Text privacyBtn1 = (Text) rootView.findComponentById(ResourceTable.Id_privacy_btn1);
        Text privacyBtn2 = (Text) rootView.findComponentById(ResourceTable.Id_privacy_btn2);
        Text privacyBtn3 = (Text) rootView.findComponentById(ResourceTable.Id_privacy_btn3);
        final Component.ClickedListener privacyClickedListener = new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Intent intent = new Intent();
                intent.setOperation(new Intent.OperationBuilder()
                    .withBundleName(getContext().getBundleName())
                    .withAbilityName(PrivacyWebAbility.class)
                    .build());
                startAbility(intent);
            }
        };
        privacyBtn1.setClickedListener(privacyClickedListener);
        privacyBtn2.setClickedListener(privacyClickedListener);
        privacyBtn3.setClickedListener(privacyClickedListener);
        Text cancel = (Text) rootView.findComponentById(ResourceTable.Id_cancel);
        cancel.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                showPrivacyDialogAgain();
                dialog.destroy();
            }
        });
        Text ok = (Text) rootView.findComponentById(ResourceTable.Id_ok);
        ok.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                // 保存已同意状态，下次不在弹出
                acceptPrivacy();
                dialog.destroy();
            }
        });
        dialog.show();
    }

    private void acceptPrivacy() {
        shareprefance.insert(USER_PRIVACY_AGREE, true);
    }

    private void showPrivacyDialogAgain() {
        final CommonDialog dialog = new CommonDialog(getContext());
        final int dialogHeightVp = 220;
        int dialogHeight = AttrHelper.vp2px(dialogHeightVp, this);
        int dialogWidth = AttrHelper.vp2px(DIALOG_WIDTH, this);
        dialog.setSize(dialogWidth, dialogHeight);
        Component rootView = LayoutScatter.getInstance(getContext()).parse(
            ResourceTable.Layout_user_privacy_again_dialog, null, true);
        dialog.setContentCustomComponent(rootView);
        Text cancelAgain = (Text) rootView.findComponentById(ResourceTable.Id_cancel_again);
        Text readAgain = (Text) rootView.findComponentById(ResourceTable.Id_read_again);
        cancelAgain.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                showPrivacyDialogLastTime();
                dialog.destroy();
            }
        });
        readAgain.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                showPrivacyDialog();
                dialog.destroy();
            }
        });
        dialog.show();
    }

    private void showPrivacyDialogLastTime() {
        final CommonDialog dialog = new CommonDialog(getContext());
        final int dialogHeightVp = 120;
        int dialogHeight = AttrHelper.vp2px(dialogHeightVp, this);
        int dialogWidth = AttrHelper.vp2px(DIALOG_WIDTH, this);
        dialog.setSize(dialogWidth, dialogHeight);
        Component rootView = LayoutScatter.getInstance(getContext()).parse(
            ResourceTable.Layout_user_privacy_last_dialog, null, true);
        dialog.setContentCustomComponent(rootView);
        Text exitApp = (Text) rootView.findComponentById(ResourceTable.Id_exit_app);
        Text readAgain = (Text) rootView.findComponentById(ResourceTable.Id_read_last);
        exitApp.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                terminateAbility();
                dialog.destroy();
            }
        });
        readAgain.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                showPrivacyDialog();
                dialog.destroy();
            }
        });
        dialog.show();
    }

    @Override
    public void onClick(Component component) {
        switch (component.getId()) {
            case ResourceTable.Id_btn_back:
                terminateAbility();
                break;
            case ResourceTable.Id_clear_phone:
                String phoneNumber = etPhoneNumber.getEditableString();
                if (phoneNumber != null && !phoneNumber.isEmpty()) {
                    etPhoneNumber.setText("");
                }
                break;
            case ResourceTable.Id_btn_get_verify_code:
                getVerifyCode();
                break;
            case ResourceTable.Id_tv_other_login:
                showToast(ResourceTable.String_login_mode);
                break;
            case ResourceTable.Id_tv_forget_password:
                showToast(ResourceTable.String_forget_password);
                break;
            case ResourceTable.Id_btn_login:
                loginByVerifyCode();
                break;
            case ResourceTable.Id_tv_user_protocol:
                showToast(ResourceTable.String_user_deal);
                break;
            case ResourceTable.Id_tv_privacy_protocol:
                showToast(ResourceTable.String_user_privacy);
                break;
            default:
                break;
        }
    }

    private void showToast(int stringResource) {
        int offset = AttrHelper.vp2px(TOAST_OFFSET, this);
        ToastDialog toast = XToast.info(this, getString(stringResource));
        toast.setOffset(0, offset);
        toast.show();
    }

    @Override
    protected void onStop() {
        countDownTimer.removeAllEvent();
        etVerifyCode.removeOnFocusChangedListener(edVerifyCodeFocusChangedListener);
        etPhoneNumber.removeOnFocusChangedListener(edPhoneNumberFocusChangedListener);
        etPhoneNumber.removeTextCursorChangedListener(phoneChangedListener);
        etVerifyCode.removeTextCursorChangedListener(verifyCodeChangedListener);
        super.onStop();
    }

    private void getVerifyCode() {
        if (isPhoneNumberIllegal() && isVerifyCodeIllegal()) {
            return;
        }
        if (btnGetVerifyCode.isEnabled()) {
            maxCountDown = MAX_COUNT_DOWN;
        }
        btnGetVerifyCode.setEnabled(false);
        countDownTimer.sendEvent(MSG_COUNT_DOWN);
    }

    private void loginByVerifyCode() {
        if (isPhoneNumberIllegal() || isVerifyCodeIllegal()) {
            return;
        }
        ToastUtil.showToastB0ttom(getContext(), " 登录成功!", new Color(AppCfig.two_black), ResourceTable.Media_ic_action_tick, 0);
        shareprefance.insert(Shareprefance.loginFlag, true);
        Intent intent = new Intent();
        intent.setOperation(new Intent.OperationBuilder()
            .withBundleName(getContext().getBundleName())
            .withAbilityName(MainLoadAbility.class)
            .build());
        startAbility(intent);
        terminateAbility();
    }

    private boolean isPhoneNumberIllegal() {
        String phoneNumber = etPhoneNumber.getEditableString();
        if (phoneNumber == null || phoneNumber.isEmpty()) {
            phoneNumberError();
            return true;
        } else if (!isPhoneNumber(phoneNumber)) {
            phoneNumberError();
            return true;
        } else {
            phoneNumberNotError();
        }
        return false;
    }

    private void phoneNumberError() {
        etPhoneNumber.setInputError(true);
        phoneNumberErrorHint.setVisibility(Component.VISIBLE);
        btnClearPhone.setVisibility(Component.INVISIBLE);
    }

    private void phoneNumberNotError() {
        etPhoneNumber.setInputError(false);
        phoneNumberErrorHint.setVisibility(Component.INVISIBLE);
    }

    private boolean isVerifyCodeIllegal() {
        String verifyCode = etVerifyCode.getEditableString();
        if (verifyCode == null || verifyCode.isEmpty()) {
            verifyCodeError();
            return true;
        } else if (verifyCode.length() != maxVerifyCodeLimit) {
            verifyCodeError();
            return true;
        } else if (etVerifyCode.isInputError()) {
            verifyCodeError();
            return true;
        }
        verifyCodeErrorHint.setVisibility(Component.INVISIBLE);
        return false;
    }

    private void verifyCodeError() {
        etVerifyCode.setInputError(true);
        verifyCodeErrorHint.setVisibility(Component.VISIBLE);
    }

    private boolean isPhoneNumber(String phoneNumber) {
        String regex = "[1][3456789]\\d{9}";
        if (phoneNumber == null || phoneNumber.isEmpty()) {
            return false;
        } else {
            return phoneNumber.matches(regex);
        }
    }
}
